﻿using System;
using System.Reflection.Emit;
using Sigil.Impl;

namespace Sigil
{
	public partial class Emit<DelegateType>
	{
		/// <summary>
		/// Loads the argument at the given index (starting at 0) for the current method onto the stack.
		/// </summary>
		public Emit<DelegateType> LoadArgument(UInt16 index)
		{
			if (ParameterTypes.Length == 0)
			{
				throw new ArgumentException("Delegate of type " + typeof(DelegateType) + " takes no parameters");
			}

			if (index >= ParameterTypes.Length)
			{
				throw new ArgumentException("index must be between 0 and " + (ParameterTypes.Length - 1) + ", inclusive");
			}

			var transitions = Wrap(StackTransition.Push(ParameterTypes[index]), "LoadArgument");

			switch (index)
			{
				case 0: UpdateState(OpCodes.Ldarg_0, transitions); return this;
				case 1: UpdateState(OpCodes.Ldarg_1, transitions); return this;
				case 2: UpdateState(OpCodes.Ldarg_2, transitions); return this;
				case 3: UpdateState(OpCodes.Ldarg_3, transitions); return this;
			}

			if (index >= Byte.MinValue && index <= Byte.MaxValue)
			{
				UpdateState(OpCodes.Ldarg_S, (Byte)index, transitions);
				return this;
			}

			Int16 asShort;
			unchecked
			{
				asShort = (Int16)index;
			}

			UpdateState(OpCodes.Ldarg, asShort, transitions);

			return this;
		}
	}
}